param(
	[Parameter(Mandatory=$false)]                             
	[string]$inputFile="inputlist.txt",     # the input file to store vdi,domain and fid list
	[Parameter(Mandatory=$false)]                             
	[switch]$inputFileSaved,               # tell if inputfile has been saved, otherwise will popup text to let user enter VDI list.
	[Parameter(Mandatory=$false)]                             
	[switch]$functionInvoked              # tell if script needs to invoke functions
)
$st=get-date
$this_path = Split-Path -Parent ($MyInvocation.MyCommand.Definition) # get the directory of this running script
$parent_path=(get-item $this_path).Parent.FullName
If( !$functionInvoked ){
	. "$parent_path\functions.ps1" # import functions to powershell from functions.ps1
}
If( $inputFile -notlike "*\*"){
    $inputFile="$this_path\$inputFile"
}
$inputlist=Get-Inputlist $inputFile $inputFileSaved
#-------------------------------------------------IE Setting Checking------------------------------------------------------------------
$ie_temp_path="$this_path\temp" # used to store each result csv file from end vdi incase the script breaks in the middle of running unexpectedly so that we can check the file and know which ones we have already checked
del "$ie_temp_path\*.csv" -Force -ErrorAction Ignore
del "$this_path\*.csv" -Force -ErrorAction Ignore
# make sure ie_regkey_list.txt exists and with ie registry keys
New-FileOrFolder $ie_temp_path -d
$ie_regkey_list="$this_path\ie_regkey_list.txt" ; New-FileOrFolder $ie_regkey_list
If( (get-content $ie_regkey_list |select -Unique|?{$_.trim() -ne ""}) -eq $null ){
	Do{ # loop above action if the ie_regkey_list is empty 
		write-host "Please save to be checked ie registry key as below format in opened txt file each line as it's empty and then press enter to continue in powershell console, please press 'Ctrl+C' if you want to quit:
		HKLM:\software\microsoft\internet explorer\
		HKCU:\software\microsoft\internet explorer\" ; notepad $ie_regkey_list
		read-host " "
	}While( (get-content $ie_regkey_list |select -Unique|?{$_.trim() -ne ""}) -eq $null  )
}
# initialize the remote script full path
$to_be_ran_in_remote_script="$this_path\get_registry_value.ps1"
If(!(test-path $to_be_ran_in_remote_script) ){ #exit if remote script not exists in this path
	write-error "Not found $to_be_ran_in_remote_script!";return
}
# initialize and clear error log to store error info for further actions
$errLog = "$this_path\err.log" ; Clear-Content $errLog -Force -ErrorAction Ignore
# script block for parellel threads running
$ie_action={
	param($line,$cnt,$ActionParams)
	try{$vdi,$domain,$fid,$env=$line.split(",").trim()}catch{}
	$this_path,$ie_temp_path=$ActionParams
	$errLog="$this_path\err.log"
	$this_machine=$env:computername
	$this_folder_remote_path=$this_path.replace(':','$')
	$remoteVDITempPath = "\\$vdi\c$\temp"
	$remote_run_script="C:\temp\get_registry_value.ps1 ie_regkey_list.txt $domain $fid" 
	write-host "Processing in $cnt-$vdi for IE Setting checking...`n"
	If(Test-Connection $vdi -quiet -count 1 -ErrorAction Ignore){ # Checking if vdi is online"
		Try{ # check if remote VDI Temp Path exists, this will aslo check if user has access to this VDI
		    If(!(test-path $remoteVDITempPath -ErrorAction Stop)){new-item -ItemType Directory -path $remoteVDITempPath -Force 1> $null}
		}Catch{
		    If($_.Exception -like "*Access is denied*"){
				Write-Host -ForegroundColor Red "$vdi-$cnt Access Denied."
				"`"Category`",`"Setting`",`"$vdi Access Denied/$fid/$domain`""|out-file -FilePath "$ie_temp_path\$vdi-ie.csv" -Encoding utf8 -Force
				"$vdi-$cnt Access Denied" >> $errLog ; return
			}
		}Finally{}
		#<-------------------------------------------- copy list file and script to the remote vdi to be ran
		"get_registry_value.ps1","ie_regkey_list.txt","combine-csv.ps1"|%{copy "$this_path\$_" "$remoteVDITempPath\" -Force -ErrorAction Ignore}
		Try{ # create the task to run the script in remote VDI
			SCHTASKS /create /s $vdi /RU System /NP /RL HIGHEST /tn get_ie_registry /sc ONCE  /st (get-date).tostring("HH:mm") /F `
			/tr "powershell.exe -NonInteractive -Executionpolicy unrestricted '$remote_run_script'" 1>$null 2>&1
		}Catch{
		    If($_.Exception -like "*Cannot create a file when that file already exists*"){ # this is an error we found in the past test, we still have no idea why it happends
				Write-Host -ForegroundColor Red "$vdi-$cnt Excepted error: Cannot create a file when that file already exists"
				"$vdi-$cnt Cannot create a file when that file already exists" >> $errLog ; return
			}
		}Finally{}
		SCHTASKS /Run /s $vdi /TN get_ie_registry 1>$null 2>&1
		Do{
		    If( (SCHTASKS /QUERY /s $vdi /TN get_ie_registry 2>$null) -imatch "Ready"){break}
		}While( $true )
		SCHTASKS /delete /s $vdi /TN get_ie_registry /F 1>$null 2>&1 ; $loopcnt=1
		Do{ 
			Try{ #<--------------- get the vdi ie info from the csv file and copy this csv file to temp folder in this running directory
				copy "$remoteVDITempPath\$vdi-ie.csv" "$ie_temp_path\" -force -ErrorAction Stop
				#<-------------------------------- delete all the remote temp files excep the result ie csv file
				"get_registry_value.ps1","ie_regkey_list.txt"|%{del "$remoteVDITempPath\$_" -force -ErrorAction Ignore}
				Write-Host -ForegroundColor Yellow "Done copying $cnt-$vdi csv file in count $loopcnt" ; break 
			}Catch{ Sleep 1
				If($loopcnt -gt 120){ # unable to find the result csv file after 60s
					Write-Host -ForegroundColor Yellow "$vdi-$cnt Waiting too long(120s) to import csv file $remoteCSVFile" ; break
				}
			}Finally{$loopcnt++}
		}While(!$rst)
	}else{ # VDI is offline
		"$vdi-$cnt is either offline or not valid" >> $errLog
		"`"Category`",`"Setting`",`"$vdi Offline/$fid/$domain`""|out-file -FilePath "$ie_temp_path\$vdi-ie.csv" -Encoding utf8 -Force
		copy "$ie_temp_path\$vdi-ie.csv" "$remoteVDITempPath\"
	}
}
Start-BulkThreads $inputlist $ie_action $this_path,$ie_temp_path 100 # trigger all remote vdis to run task to collect ie registry values(2-3 mins)
#<--------------------------------------------------- combine single csv file to be one total csv file
If( $inputlist.count -gt 2 ){
	$combine_csv_action={
		param($line,$cnt,$ActionParams)
		$vdi1,$vdi2=$ActionParams[($cnt * 2-2),($cnt * 2 -1)]
		$vdi1=$vdi1.split(',')[0] ; $vdi2=$vdi2.split(',')[0]
		$csv1="$vdi1-ie.csv" ; $csv2="$vdi2-ie.csv"
		write-host "Combinding $cnt : $($cnt * 2 -1)-$($cnt * 2) csv files |$csv1|<-->|$csv2|`n"
		$remote_run_script="C:\temp\combine-csv.ps1 $csv1 $csv2"
		move-item "\\$vdi2\c$\temp\$csv2" "\\$vdi1\c$\temp\" -force
		Do{
			$rst=test-path "\\$vdi1\c$\temp\$csv2" -ErrorAction Ignore
			sleep 1
		}While( !$rst )
		SCHTASKS /create /s $vdi1 /RU System /NP /RL HIGHEST /tn combine_csv /sc ONCE  /st (get-date).tostring("HH:mm") /F `
		/tr "powershell.exe -NonInteractive -Executionpolicy unrestricted '$remote_run_script'" 1>$null 2>&1
		SCHTASKS /Run /s $vdi1 /TN combine_csv 1>$null 2>&1
		return $vdi1
	}
	$check_task_action={
		param($vdi,$cnt,$taskname)
		Do{
			If( (SCHTASKS /QUERY /s $vdi /TN $taskname 2>$null) -imatch "Ready"){break}
			sleep 1
		}While( $true )
		SCHTASKS /delete /s $vdi /TN $taskname /F 1>$null 2>&1 
		write-host "Done running task in $cnt $vdi"
	}
	Do{
		$inputlist_cnt=$inputlist.count
		If( ($inputlist_cnt % 2) -eq 1 ){
			$last_vdi=$inputlist[-1]
		}else{$last_vdi=$null}
		[string[]]$inputlist=Start-BulkThreads @(1.. [math]::Truncate($inputlist_cnt/2)) $combine_csv_action $inputlist -maxCnt 50|sort
		Start-BulkThreads $inputlist $check_task_action combine_csv -maxCnt 50
		If( $last_vdi ){
			$inputlist+=$last_vdi
		}
	}While( $inputlist.count -gt 1)
	copy "\\$inputlist\c$\temp\$inputlist-ie.csv" "$this_path\ie.csv"
	$run_secs=[math]::Round(((get-date)-$st).totalseconds)
	Write-Host -ForegroundColor Yellow "Done export ie settings to '$this_path\ie.csv' in $run_secs s."
}else{  #<---------------------------- exclude equal values if there are 2 csv files
	$total_ie_csv_files=(dir $this_path\temp\*.csv).FullName|sort
	$csv_hashtable1=[ordered]@{};$csv_hashtable2=[ordered]@{} ; $csv_settings1=@();$csv_settings2=@()
	$csv1,$csv2=$total_ie_csv_files|%{Get-Content $_ -ReadCount 0}
	$rst=compare $csv1 $csv2
	$rst|?{$_.SideIndicator -eq "<="}|%{ # load 1st csv settings and values
		$line=$_.InputObject ; $setting=($line -split('","'))[1]
		$csv_settings1+=$setting
		$csv_hashtable1.Add($setting,$line)
	}
	$rst|?{$_.SideIndicator -eq "=>"}|%{ # load 2nd csv settings and values
		$line=$_.InputObject ; $setting=($line -split('","'))[1]
		$csv_settings2+=$setting
		$csv_hashtable2.Add($setting,$line)
	}
	$total_ie_info=@()
	Foreach( $setting in $csv_settings1){ # manage 1st csv file data
		If( $setting -inotin $csv_settings2){
			$value=',"N/A"'
		}else{
			$value=','+($csv_hashtable2.$setting -split('",'))[2]
		}
		$total_ie_info+=$csv_hashtable1.$setting+$value
	}
	$csv_settings2|?{$_ -inotin $csv_settings1}|%{ # manager 2nd csv file data
		$value=$csv_hashtable2.$_
		$sec_num=$value.LastIndexOf('",')
		$total_ie_info+=$value.Substring(0,$sec_num+3)+"N/A$($value.Substring($sec_num))"
	}
	Export-Result $total_ie_info "ie settings" "$this_path\ie.csv" ([math]::Round(((get-date)-$st).totalseconds)) -outfile
}